#ifndef MYPROGRAMM_H
#define MYPROGRAMM_H

#include <QObject>
#include <QtGui/QApplication>
#include <QMouseEvent>
#include "dcpp/ClientListener.h"
#include "dcpp/ConnectionManagerListener.h"
#include "dcpp/DownloadManagerListener.h"
#include "dcpp/FavoriteManagerListener.h"
#include "dcpp/FinishedManagerListener.h"
#include "dcpp/HashManagerListener.h"
#include "dcpp/QueueManagerListener.h"
#include "dcpp/SearchManagerListener.h"
#include "dcpp/UploadManagerListener.h"
#include "dcpp/UserConnectionListener.h"
#include "dcpp/stdinc.h"
#include "dcpp/typedefs.h"

using std::string;

class ViewModel;
class QmlApplicationViewer;
class HubData;
namespace dcpp {
    class Client;
}

typedef QList<HubData*> Hubs;

/** Основной класс приложения.
 *
 * Вместо наследования от QApplication применяю агрегирование, чтобы
 * использовать для создания экземпляра QApplication стандартну фабрику.
 * @author Василий Почкаенко. */
class MyProgramm : public QObject,
        public dcpp::ConnectionManagerListener,
        public dcpp::ClientListener,
        public dcpp::DownloadManagerListener,
        public dcpp::FavoriteManagerListener,
        public dcpp::FinishedManagerListener,
        public dcpp::HashManagerListener,
        public dcpp::QueueManagerListener,
        public dcpp::SearchManagerListener,
        public dcpp::UploadManagerListener,
        public dcpp::UserConnectionListener{
    Q_OBJECT
private:
    ViewModel * m_vm;
    QmlApplicationViewer * m_viewer;

    bool connectHub(const QString & adress, const QString &nick);

    QPoint m_oldPos;

    void SetDefSettings();

    void runSearch(QString s);
private slots:
    /** Открыть настройки в новом окне.*/
    void openSettingWindow();
public:
    explicit MyProgramm(QApplication *parent = 0);
    ~MyProgramm();

    Q_INVOKABLE void moveWindows ( int x, int y );
    Q_INVOKABLE void clearPos ();





    // Слушатель dcpp::ClientManager

    void on(dcpp::ClientListener::Connecting, dcpp::Client*) noexcept;
    void on(dcpp::ClientListener::Connected, dcpp::Client*) noexcept;
    void on(dcpp::ClientListener::UserUpdated, dcpp::Client*, const dcpp::OnlineUser&) noexcept;
    void on(dcpp::ClientListener::UsersUpdated, dcpp::Client*, const dcpp::OnlineUserList&) noexcept;
    void on(dcpp::ClientListener::UserRemoved, dcpp::Client*, const dcpp::OnlineUser&) noexcept;
    void on(dcpp::ClientListener::Redirect, dcpp::Client*, const string&) noexcept;
    void on(dcpp::ClientListener::Failed, dcpp::Client*, const string&) noexcept;
    void on(dcpp::ClientListener::GetPassword, dcpp::Client*) noexcept;
    void on(dcpp::ClientListener::HubUpdated, dcpp::Client*) noexcept;
    void on(dcpp::ClientListener::Message, dcpp::Client*, const dcpp::ChatMessage&) noexcept;
    void on(dcpp::ClientListener::StatusMessage, dcpp::Client*, const string&, int = FLAG_NORMAL) noexcept;
    void on(dcpp::ClientListener::HubUserCommand, dcpp::Client*, int, int, const string&, const string&) noexcept;
    void on(dcpp::ClientListener::HubFull, dcpp::Client*) noexcept;
    void on(dcpp::ClientListener::NickTaken, dcpp::Client*) noexcept;
    void on(dcpp::ClientListener::SearchFlood, dcpp::Client*, const string&) noexcept;
    void on(dcpp::ClientListener::NmdcSearch, dcpp::Client*, const string&, int, int64_t, int, const string&) noexcept;
    void on(dcpp::ClientListener::AdcSearch, dcpp::Client*, const dcpp::AdcCommand&, const dcpp::CID&) noexcept;




    // Слушатель QueueManager

    void on(dcpp::QueueManagerListener::Added, dcpp::QueueItem*) noexcept;
    void on(dcpp::QueueManagerListener::Finished, dcpp::QueueItem*, const string&, int64_t) noexcept;
    void on(dcpp::QueueManagerListener::Removed, dcpp::QueueItem*) noexcept;
    void on(dcpp::QueueManagerListener::Moved, dcpp::QueueItem*, const string&) noexcept;
    void on(dcpp::QueueManagerListener::QueueManagerListener::SourcesUpdated, dcpp::QueueItem*) noexcept;
    void on(dcpp::QueueManagerListener::QueueManagerListener::StatusUpdated, dcpp::QueueItem*) noexcept;
    void on(dcpp::QueueManagerListener::SearchStringUpdated, dcpp::QueueItem*) noexcept;
    void on(dcpp::QueueManagerListener::PartialList, const dcpp::HintedUser&, const string&) noexcept;

    void on(dcpp::QueueManagerListener::RecheckStarted, const string&) noexcept;
    void on(dcpp::QueueManagerListener::RecheckNoFile, const string&) noexcept;
    void on(dcpp::QueueManagerListener::RecheckFileTooSmall, const string&) noexcept;
    void on(dcpp::QueueManagerListener::RecheckDownloadsRunning, const string&) noexcept;
    void on(dcpp::QueueManagerListener::RecheckNoTree, const string&) noexcept;
    void on(dcpp::QueueManagerListener::RecheckAlreadyFinished, const string&) noexcept;
    void on(dcpp::QueueManagerListener::RecheckDone, const string&) noexcept;

    void on(dcpp::QueueManagerListener::FileMoved, const string&) noexcept;

    void on(dcpp::QueueManagerListener::CRCFailed, dcpp::Download*, const string&) noexcept;
    void on(dcpp::QueueManagerListener::CRCChecked, dcpp::Download*) noexcept;




    // Слушатель SearchManager

    void on(dcpp::SearchManagerListener::SR, const dcpp::SearchResultPtr&) noexcept;


    // Слушатель ConnectionManager

    void on(dcpp::ConnectionManagerListener::Added, dcpp::ConnectionQueueItem*) noexcept;
    void on(dcpp::ConnectionManagerListener::Connected, dcpp::ConnectionQueueItem*) noexcept;
    void on(dcpp::ConnectionManagerListener::Removed, dcpp::ConnectionQueueItem*) noexcept;
    void on(dcpp::ConnectionManagerListener::Failed, dcpp::ConnectionQueueItem*, const string&) noexcept;
    void on(dcpp::ConnectionManagerListener::StatusChanged, dcpp::ConnectionQueueItem*) noexcept;






    // Млушатель DownloadManager

    /**
     * This is the first message sent before a download starts.
     * No other messages will be sent before this.
     */
    void on(dcpp::DownloadManagerListener::Requesting, dcpp::Download*) noexcept;

    /**
     * This is the first message sent before a download starts.
     */
    void on(dcpp::DownloadManagerListener::Starting, dcpp::Download*) noexcept;

    /**
     * Sent once a second if something has actually been downloaded.
     */
    void on(dcpp::DownloadManagerListener::Tick, const dcpp::DownloadList&) noexcept;

    /**
     * This is the last message sent before a download is deleted.
     * No more messages will be sent after it.
     */
    void on(dcpp::DownloadManagerListener::Complete, dcpp::Download*) noexcept;

    /**
     * This indicates some sort of failure with a particular download.
     * No more messages will be sent after it.
     *
     * @remarks Should send an error code instead of a string and let the GUI
     * display an error string.
     */
    void on(dcpp::DownloadManagerListener::Failed, dcpp::Download*, const string&) noexcept;




    // Слушатель FavoriteManager

    void on(dcpp::FavoriteManagerListener::DownloadStarting, const string&) noexcept;
    void on(dcpp::FavoriteManagerListener::DownloadFailed, const string&) noexcept;
    void on(dcpp::FavoriteManagerListener::DownloadFinished, const string&, bool) noexcept;
    void on(dcpp::FavoriteManagerListener::FavoriteAdded, const dcpp::FavoriteHubEntryPtr) noexcept;
    void on(dcpp::FavoriteManagerListener::FavoriteRemoved, const dcpp::FavoriteHubEntryPtr) noexcept;
    void on(dcpp::FavoriteManagerListener::UserAdded, const dcpp::FavoriteUser&) noexcept;
    void on(dcpp::FavoriteManagerListener::UserUpdated, const dcpp::FavoriteUser&) noexcept;
    void on(dcpp::FavoriteManagerListener::UserRemoved, const dcpp::FavoriteUser&) noexcept;
    void on(dcpp::FavoriteManagerListener::StatusChanged, const dcpp::UserPtr&) noexcept;
    void on(dcpp::FavoriteManagerListener::LoadedFromCache, const string&, const string&) noexcept;




    // Слушатель FinishedManager

    void on(dcpp::FinishedManagerListener::AddedFile, bool, const string&, const dcpp::FinishedFileItemPtr&) noexcept;
    void on(dcpp::FinishedManagerListener::AddedUser, bool, const dcpp::HintedUser&, const dcpp::FinishedUserItemPtr&) noexcept;
    void on(dcpp::FinishedManagerListener::UpdatedFile, bool, const string&, const dcpp::FinishedFileItemPtr&) noexcept;
    void on(dcpp::FinishedManagerListener::UpdatedUser, bool, const dcpp::HintedUser&) noexcept;
    void on(dcpp::FinishedManagerListener::RemovedFile, bool, const string&) noexcept;
    void on(dcpp::FinishedManagerListener::RemovedUser, bool, const dcpp::HintedUser&) noexcept;
    void on(dcpp::FinishedManagerListener::RemovedAll, bool) noexcept;




    // Слушатель HashManager

    void on(dcpp::HashManagerListener::TTHDone, const string& /* fileName */, const dcpp::TTHValue& /* root */) noexcept;






    // Слушатель UploadManager
    void on(dcpp::UploadManagerListener::Starting, dcpp::Upload*) noexcept;
    void on(dcpp::UploadManagerListener::Tick, const dcpp::UploadList&) noexcept;
    void on(dcpp::UploadManagerListener::Complete, dcpp::Upload*) noexcept;
    void on(dcpp::UploadManagerListener::Failed, dcpp::Upload*, const string&) noexcept;
    void on(dcpp::UploadManagerListener::WaitingAddFile, const dcpp::HintedUser&, const string&) noexcept;
    void on(dcpp::UploadManagerListener::WaitingRemoveUser, const dcpp::HintedUser&) noexcept;





    // Слушатель UserConnection
    void on(dcpp::UserConnectionListener::BytesSent, dcpp::UserConnection*, size_t, size_t) noexcept;
    void on(dcpp::UserConnectionListener::Connected, dcpp::UserConnection*) noexcept;
    void on(dcpp::UserConnectionListener::Data, dcpp::UserConnection*, const uint8_t*, size_t) noexcept;
    void on(dcpp::UserConnectionListener::Failed, dcpp::UserConnection*, const string&) noexcept;
    void on(dcpp::UserConnectionListener::ProtocolError, dcpp::UserConnection*, const string&) noexcept;
    void on(dcpp::UserConnectionListener::CLock, dcpp::UserConnection*, const string&, const string&) noexcept;
    void on(dcpp::UserConnectionListener::Key, dcpp::UserConnection*, const string&) noexcept;
    void on(dcpp::UserConnectionListener::Direction, dcpp::UserConnection*, const string&, const string&) noexcept;
    void on(dcpp::UserConnectionListener::Get, dcpp::UserConnection*, const string&, int64_t) noexcept;
    void on(dcpp::UserConnectionListener::Send, dcpp::UserConnection*) noexcept;
    void on(dcpp::UserConnectionListener::GetListLength, dcpp::UserConnection*) noexcept;
    void on(dcpp::UserConnectionListener::MaxedOut, dcpp::UserConnection*) noexcept;
    void on(dcpp::UserConnectionListener::ModeChange, dcpp::UserConnection*) noexcept;
    void on(dcpp::UserConnectionListener::MyNick, dcpp::UserConnection*, const string&) noexcept;
    void on(dcpp::UserConnectionListener::TransmitDone, dcpp::UserConnection*) noexcept;
    void on(dcpp::UserConnectionListener::Supports, dcpp::UserConnection*, const dcpp::StringList&) noexcept;
    void on(dcpp::UserConnectionListener::FileNotAvailable, dcpp::UserConnection*) noexcept;
    void on(dcpp::UserConnectionListener::Updated, dcpp::UserConnection*) noexcept;

    void on(dcpp::AdcCommand::SUP, dcpp::UserConnection*, const dcpp::AdcCommand&) noexcept;
    void on(dcpp::AdcCommand::INF, dcpp::UserConnection*, const dcpp::AdcCommand&) noexcept;
    void on(dcpp::AdcCommand::GET, dcpp::UserConnection*, const dcpp::AdcCommand&) noexcept;
    void on(dcpp::AdcCommand::SND, dcpp::UserConnection*, const dcpp::AdcCommand&) noexcept;
    void on(dcpp::AdcCommand::STA, dcpp::UserConnection*, const dcpp::AdcCommand&) noexcept;
    void on(dcpp::AdcCommand::RES, dcpp::UserConnection*, const dcpp::AdcCommand&) noexcept;
    void on(dcpp::AdcCommand::GFI, dcpp::UserConnection*, const dcpp::AdcCommand&) noexcept;
signals:
    
public slots:
    
};

#endif // MYPROGRAMM_H
